structure StringExtra = struct
    val empty = "";

    fun split sep str =
        let
            val chars = String.explode str;
            val sep_chars = String.explode sep;
            val sep_len = length sep_chars;
            val prefix_pred = ListExtra.is_list_prefix sep_chars;
            fun iter (nil, collected_chars, parts) = String.implode (rev collected_chars) :: parts
              | iter (remaining_chars as (c::cs), collected_chars, parts) =
                if prefix_pred remaining_chars
                then
                    (* drop the separator, begin anew collecting chars until next separator, *)
                    iter (List.drop (remaining_chars, sep_len),
                          [],
                          String.implode (rev collected_chars) :: parts)
                else
                    (* collect characters, which are not part of the prefix *)
                    iter (cs, c :: collected_chars, parts)
        in
            rev (iter (chars, [], []))
        end;

    fun replace searched replacement str =
        let
            val len_searched = String.size searched;

            val chars = String.explode str;
            val searched_chars = String.explode searched;
            val replacement_chars = String.explode replacement;
            val starts_with_searched = ListExtra.is_list_prefix searched_chars;

            fun iter nil = []
              | iter remaining_chars =
                if starts_with_searched remaining_chars
                then
                    ListExtra.prepend replacement_chars
                                      (iter (List.drop (remaining_chars, len_searched)))
                else
                    (hd remaining_chars) :: iter (tl remaining_chars);
        in
            String.implode (iter chars)
        end;

    fun trim_left pred str =
        let
            fun iter nil = []
              | iter (chars as (c::cs)) =
                if pred c
                then iter cs
                else chars
        in
            String.implode (iter (String.explode str))
        end;
end;
